package cn.cmvideo.springboot.algorithm;

import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

/**
 * 求数组元素的排列和组合<br>
 * 1.无重复数字的数组，求组合<br>
 * 2.有重复数字的数组，求组合<br>
 * 3.无重复数字的数组，求排列<br>
 * 4.有重复数字的数组，求排列<br>
 * 
 * <p>
 * 解决方式：通用思路（递归）
 * </p>
 * <p>
 * 定义一个函数：从候选集candidate中选取一个组合prefix，每次从候选集candidate中remove一个数，并加入前缀prefix，
 * 打印prefix； 再递归从新的candidate中remove下一个数，并加入prefix
 * </p>
 * <p>
 * 对于重复的控制：采用hashset保存prefix，打印之前，判断hashset中是否包含当前生成的prefix，没有则打印，并加入hashset；
 * 有则不打印
 * </p>
 * <p>
 * 组合--》排列：只需在打印前加一个判断：若候选集candidate为空，表示遍历完一次，生成一个排列，可打印
 * </p>
 * 
 * @author Administrator
 *
 */
public class ListAllGroup
{
	public static void main(String[] args)
	{
		String[] array = { "1", "2", "3" };
		// String[] repeate = { "1", "2", "1" };
		ListAllGroup test = new ListAllGroup();

		System.out.println("**********no repeate list*******");
		test.listAllNoRepeate(Arrays.asList(array), "");// 初始化prefix = ""

		// System.out.println("**********repeate list*******");
		// HashSet<String> noRepeateSet = new HashSet<String>();
		// test.listAllRepeate(Arrays.asList(repeate), "", noRepeateSet);

		// System.out.println("**************no repeate premutation********************");
		// test.premutationNoRepeate(Arrays.asList(array), "");

		// System.out.println("*********************repeate premutation**********************");
		// HashSet<String> repeateSet = new HashSet<String>();
		// test.premutationRepeate(Arrays.asList(repeate), "", repeateSet);

	}

	// 无重复的组合
	public void listAllNoRepeate(List<String> candidate, String prefix)
	{
		if (prefix.length() != 0)
			System.out.println(prefix);// 结果长度不为0,则打印输出该组合

		for (int i = 0; i < candidate.size(); i++)
		{
			// 将list转换成linklist链表，方便操作
			List<String> tempList = new LinkedList<String>(candidate);
			// templist减少一个数字，并暂存templist中去除的数字
			String tempString = (String) tempList.remove(i);
			// 递归
			listAllNoRepeate(tempList, prefix + tempString);
		}
	}

	// 有重复的组合,加入hashset
	public void listAllRepeate(List<String> candidate, String prefix, HashSet<String> res)
	{
		if (prefix.length() != 0 && !res.contains(prefix))
		{
			System.out.println(prefix);
			res.add(prefix);
		}

		for (int i = 0; i < candidate.size(); i++)
		{
			List<String> tempList = new LinkedList<String>(candidate);
			String tempString = tempList.remove(i);
			listAllRepeate(tempList, prefix + tempString, res);// 递归
		}
	}

	// 无重复的全排列，加入判断candidate.size() == 0
	public void premutationNoRepeate(List<String> candidate, String prefix)
	{
		if (candidate.size() == 0)
		{
			System.out.println(prefix);
		}

		for (int i = 0; i < candidate.size(); i++)
		{
			List<String> tempList = new LinkedList<String>(candidate);
			String tempString = tempList.remove(i);
			premutationNoRepeate(tempList, prefix + tempString);
		}
	}

	// 有重复的全排列，加入hashset辅助判断输出
	public void premutationRepeate(List<String> candidate, String prefix, HashSet<String> res)
	{
		if (candidate.size() == 0 && !res.contains(prefix))
		{
			System.out.println(prefix);
			res.add(prefix);
		}

		for (int i = 0; i < candidate.size(); i++)
		{
			List<String> tempList = new LinkedList<String>(candidate);
			String tempString = tempList.remove(i);
			premutationRepeate(tempList, prefix + tempString, res);
		}
	}

}
